#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define FORMAT "[%s@%s %s]# "
#define SIZE 1024


//定义全局变量
char* g_argv[128];
int g_argc=0;

//获取用户名
const char* GetUserName()
{
	const char* Usr = getenv("USER");
	return Usr == NULL ? "None" : Usr;
}

//获取主机名
const char* GetHostName()
{
	const char* HostName = getenv("HOSTNAME");
	return HostName == NULL ? "None" : HostName;
}

//获取路径
const char* GetPwd()
{
	const char* Pwd = getenv("PWD");
	return Pwd == NULL ? "None" : Pwd;
}

//创建格式化命令行提示符
void MakeCommandLine(char cmd_prompot[], int size)
{
	snprintf(cmd_prompot, size, FORMAT, GetUserName(), GetHostName(), GetPwd());
}

//输出命令行提示符
void PrintCommandPrompt()
{
	char prompt[SIZE];
	MakeCommandLine(prompt, sizeof(prompt));
	printf("%s", prompt);
	fflush(stdout);
}

//获取用户输入命令
//获取用户输入命令
bool GetCommandLine(char* out, int size)
{
	char* c = fgets(out, size, stdin);
	if (c == NULL)
	{
		return false;
	}
    
    //删除命令行输入最后的回车
    out[strlen(out)-1]='\0';
    if(sizeof(out)==0) return false;
    return true;
}

//分解输入命令
bool CommandParse(char* commandline)
{
    g_argc=0;
    //分隔符SEP设置为空格
#define SEP " "
    g_argv[g_argc++] = strtok(commandline, SEP);
    while(g_argv[g_argc++] = strtok(nullptr, SEP));
    
    g_argc--;
    return true;
}

//打印argv
void PrintArgv()
{
    for(int i=0; i<g_argc; i++)
    {
        printf("argv[%d]->%s\n", i, g_argv[i]);
    }
    printf("%d\n",g_argc);
}


//子进程执行命令
void Execute()
{
     pid_t id = fork();
    if(id == 0)
     {
         //子进程
         execvp(g_argv[0], g_argv);            
         

         exit(1);
     }
    //父进程
    waitpid(id, nullptr, 0);//阻塞等待

}

int main()
{
	//
	//test01();
	//
	//*************************************************
	
    while(1)
    {
        //输出命令行提示符
	    PrintCommandPrompt();

	    //获取输入命令
        char command[SIZE];
        if(! GetCommandLine(command, sizeof(command)))
            continue;
       
        //命令语法分析
        CommandParse(command);
        //PrintArgv();//命令拆解打印
        
        //执行命令    
        Execute();
    }

	return 0;
}








